package com.payment.common.wxutils.test;

import com.alibaba.fastjson.JSONObject;
import com.payment.service.impl.WxServiceImpl;
import com.payment.common.utils.DateUtils;
import com.payment.common.utils.IpAddressUtil;
import com.payment.common.utils.ResultDataDto;
import com.payment.common.utils.UUIDGenerator;
import com.payment.common.wxutils.*;
import org.jdom.JDOMException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

public class wxH5 {

    private static final Logger logger = LoggerFactory
            .getLogger(WxServiceImpl.class);
    @Autowired
    private WxConfigUtil wxConfigUtil;


    /**
     * 纯H5页面支付
     * @return
     */
    public ResultDataDto weixinPayH5() {

        String code = DateUtils.dateToString(new Date());

        logger.info("订单号：{}发起H5支付",code);

        String mweb_url = "";
        try {
            // 账号信息
            String key = wxConfigUtil.getAPI_KEY(); // key
            String trade_type = "MWEB";// 交易类型 H5 支付
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
            packageParams.put("appid", wxConfigUtil.getAPP_ID());// 公众账号ID
            packageParams.put("mch_id", wxConfigUtil.getMCH_ID());// 商户号*/
            WxConfigUtil.commonParams(packageParams);
            packageParams.put("product_id", "");// 商品ID
            packageParams.put("body", "");// 商品描述
            packageParams.put("out_trade_no", code);// 商户订单号
            String totalFee = "";//传过来金额
            totalFee = CommonUtil.subZeroAndDot(totalFee);
            packageParams.put("total_fee", Integer.valueOf(totalFee));// 总金额
            // H5支付要求商户在统一下单接口中上传用户真实ip地址 spbill_create_ip
            String ip = IpAddressUtil.getHostIp();
            packageParams.put("spbill_create_ip",ip );// 发起人IP地址
            packageParams.put("notify_url", wxConfigUtil.getNB_NOTIFY_URL());// 回调地址，handlePayNotify() 方法
            packageParams.put("trade_type", trade_type);// 交易类型
            packageParams.put("nonce_str", UUIDGenerator.getUUID());
            // H5支付专用
            JSONObject value = new JSONObject();
            value.put("type", "H5");
            value.put("wap_url","http://www.bdhg.com.cn");
            value.put("wap_name", "xxx集团");// WAP 网站名
            JSONObject scene_info = new JSONObject();
            scene_info.put("h5_info", value);
            packageParams.put("scene_info", scene_info.toString());

            String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);
            packageParams.put("sign", sign);// 签名
            boolean isSign = PayCommonUtil.isTenpaySign("UTF-8",packageParams,key);
            if (!isSign){
                return ResultDataDto.error("签名不合法");
            }

            //保存订单信息逻辑

            //发起支付
            String requestXML = PayCommonUtil.getRequestXml(packageParams);
            String resXml = HttpUtil.postData(WxConfigUtil.UNIFIED_ORDER_URL,requestXML);
            Map map = XMLUtil.doXMLParse(resXml);
            String returnCode = (String) map.get("return_code");
            if ("SUCCESS".equals(returnCode)) {
                String resultCode = (String) map.get("result_code");
                if ("SUCCESS".equals(resultCode)) {
                    logger.info("订单号：{}发起H5支付成功", "no");
                    String url = (String) map.get("mweb_url");
                    mweb_url = URLEncoder.encode( url+"&redirect_url="+ wxConfigUtil.getSERVICE_URL(),"utf-8");
                    //payOrderMapper.insert(orderInfo);
                    return ResultDataDto.ok(mweb_url);
                } else {
                    String errCodeDes = (String) map.get("err_code_des");
                    logger.info("订单号：{}发起H5支付(系统)失败:{}",
                            "no", errCodeDes);
                    return ResultDataDto.error("订单号："+"no"+" 发起H5支付(系统)失败:"+errCodeDes);
                }
            } else {
                String returnMsg = (String) map.get("return_msg");
                logger.info("(订单号：{}发起H5支付(通信)失败:{}", "no",
                        returnMsg);
                return ResultDataDto.error("订单号："+"no"+" 发起H5支付(系统)失败:"+returnMsg);
            }
        } catch (Exception e) {
            logger.error("订单号：{}发起H5支付失败(系统异常))","no", e);
        }
        return ResultDataDto.error("支付失败");
    }


    /**
     * 订单查询
     * @param outTradeNo
     * @return
     */
    public ResultDataDto query(String outTradeNo) {
        try {
            logger.info("订单号：{}发起支付查询",outTradeNo);
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
            packageParams.put("appid", wxConfigUtil.getAPP_ID());// 公众账号ID
            packageParams.put("mch_id", wxConfigUtil.getMCH_ID());// 商户号*/
            WxConfigUtil.commonParams(packageParams);
            packageParams.put("out_trade_no", outTradeNo);// 商户订单号
            packageParams.put("nonce_str", UUIDGenerator.getUUID());
            String key = wxConfigUtil.getAPI_KEY(); // key
            String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);
            boolean isSign = PayCommonUtil.isTenpaySign("UTF-8",packageParams,key);
            if (!isSign){
                return ResultDataDto.error("签名不合法");
            }
            packageParams.put("sign", sign);// 签名

            //发起支付
            String requestXML = PayCommonUtil.getRequestXml(packageParams);
            String resXml = HttpUtil.postData(WxConfigUtil.CHECK_ORDER_URL,requestXML);
            Map map = XMLUtil.doXMLParse(resXml);
            String returnCode = (String) map.get("return_code");
            if ("SUCCESS".equals(returnCode)) {
                String resultCode = (String) map.get("result_code");
                if ("SUCCESS".equals(resultCode)) {
                    String returnTradeState = (String) map.get("trade_state");
                    if ("SUCCESS".equals(returnTradeState)) {
                        logger.info("订单号：{}发起H5支付查询成功", outTradeNo);
                        return ResultDataDto.ok("支付成功");
                    }
                } else {
                    String errCodeDes = (String) map.get("err_code_des");
                    logger.info("订单号：{}发起H5支付(系统)查询失败:{}",
                            outTradeNo, errCodeDes);
                    return ResultDataDto.error("订单号："+outTradeNo +" 发起H5支付查询(系统)失败:"+errCodeDes);
                }
            } else {
                String returnMsg = (String) map.get("return_msg");
                logger.info("(订单号：{}发起H5支付(通信)失败:{}", outTradeNo,returnMsg);
                return ResultDataDto.error("订单号："+outTradeNo+" 发起H5支付(系统)查询失败:"+returnMsg);
            }
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }



    /**
     * 异步通知 支付结果
     * @param request
     * @param response
     */
    public void handlePayNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            // 读取参数
            InputStream inputStream = request.getInputStream();
            StringBuffer sb = new StringBuffer();
            String s;
            BufferedReader in = null;

            in = new BufferedReader(new InputStreamReader(
                    inputStream, "UTF-8"));

            while ((s = in.readLine()) != null) {
                sb.append(s);
            }
            in.close();
            inputStream.close();

            // 解析xml成map
            Map<String, String> map = XMLUtil.doXMLParse(sb.toString());

            // 过滤空 设置 TreeMap
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
            Iterator it = map.keySet().iterator();
            while (it.hasNext()) {
                String parameter = (String) it.next();
                String parameterValue = map.get(parameter);
                String v = "";
                if (null != parameterValue) {
                    v = parameterValue.trim();
                }
                packageParams.put(parameter, v);
            }
            // 账号信息
            String key = wxConfigUtil.getAPI_KEY(); // key
            // 判断签名是否正确
            if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {
                logger.info("微信支付成功回调");
                // ------------------------------
                // 处理业务开始
                // ------------------------------
                // 这里是支付成功
                String orderNo = (String) packageParams.get("out_trade_no");
                String resXml = "";
                if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
                    // 这里是支付成功
                    logger.info("微信订单号{}付款成功", orderNo);
                    // 这里 根据实际业务场景 做相应的操作
                    // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                    resXml = "<xml>"
                            + "<return_code><![CDATA[SUCCESS]]></return_code>"
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                } else {
                    logger.info("支付失败,错误信息：{}", packageParams.get("err_code"));
                    resXml = "<xml>"
                            + "<return_code><![CDATA[FAIL]]></return_code>"
                            + "<return_msg><![CDATA[报文为空]]></return_msg>"
                            + "</xml> ";
                }
                // ------------------------------
                // 处理业务完毕
                // ------------------------------
                BufferedOutputStream out = new BufferedOutputStream(
                        response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
            } else {
                logger.info("通知签名验证失败");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }catch (JDOMException e) {
            e.printStackTrace();
        }
    }
}
